<?php
/*
	This file is part of Core. Copyright © 2007, Emanuele Vulcano.

	Core is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	Core is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Core; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
	
*/

require_once 'CDynamic.php';
require_once 'CCopy.php';

function CRef(&$what) { return array(&$what); }
function &CDeref($ref) { return $ref[0]; }

function &CTag($name, $content = null) {
	$t = &new CTag($name);
	if (!is_null($content)) $t->Content($content);
	return $t;
}

class CTag extends CDynamic {
	var $Name;
	var $Attributes = array();
	var $Content = null;
	var $Bound = array();
	var $Source = null;
	
	function Init($name) {
		$this->Name = $name;
	}
	
	function Attribute($name, $value) {
		$this->Attributes[$name] = $value;
		return $this; // PHP 5 only
	}
	
	function Bind($what, $property) {
		$this->Bound[$what] = $property;
		return $this; // PHP 5 only
	}
	
	function Source(&$from) {
		$this->Source = &$from;
		foreach ($this->Bound as $name => $val)
			$this->$name(CGetKey($from, $val));
		return $this; // PHP 5 only
	}
			
	function CloningClass() { return get_class($this); }
	function &CreateClone() {
		$c = CCopy($this);
		if (is_object($this->Content))
			$c->Content($this->Content->CreateClone());
		else {
			if (is_object($this->Content[0])) {
				$x = array();
				foreach ($this->Content as $o)
					$x[] = $o->CreateClone();
				$c->Content($x);
			} else
				$c->Content($this->Content);
		}
		
		return $c;
	}
	
	function Content($x) {
		if (func_num_args() == 0)
			$this->Content = $x;
		else
			$this->Content = func_get_args();
		return $this;
	}
	
	function ContentRef(&$x) { // PHP 4 only
		$this->Content = &$x;
	}
	
	function Show() {
		echo "<{$this->Name}";
		if (is_array($this->Attributes) && sizeof($this->Attributes) > 0) {
			foreach ($this->Attributes as $name => $value) {
				if ((is_bool($value) && !$value) || $value === null)
					continue;
				
				if (is_bool($value) && $value)
					echo ' ' . CHEsc($name) . '="' . CHEsc($name) . '"';
				else
					echo ' ' . CHEsc($name) . '="' . CHEsc($value) . '"';
			}
		}
		
		if (is_array($this->Content) && sizeof($this->Content) > 0) {
			echo '>';
			$x = $this->Content;
			foreach ($x as $item)
				CShow($item);
			echo "</{$this->Name}>";
		} else if (!is_null($this->Content)) {
			echo '>';
			CShow($this->Content);
			echo "</{$this->Name}>";
		} else
			echo ' />';
	}
	
	function __toString() {
		ob_start();
		$this->Show();
		return ob_get_clean();
	}
	
	function _CallMethod($name, $args, &$ret) {
		if (substr($name, -4) == CSymbol('From') && strlen($name) > 4) {
			$key = substr($name, 0, -4);
			$this->Bind(strtolower($key), $args[0]);
			$ret = $this;
			return true;
		}
		
		$this->Attribute(strtolower($name), $args[0]);
		$ret = $this;
		return true;
	}
	
	function EachSource($many) { $this->Source($many[0]); return $this; /* PHP 5 only */ }
	function EachContent($many) { $this->Content($many[0]); return $this; /* PHP 5 only */ }
	
	function &Many($name) {
		$t = &new CTagTemplate($name);
		return $t;
	}
}

class CTagTemplate extends CTag {
	function EachSource($many) {
		$x = array();
		foreach ($many as $source) {
			$newMe = &$this->CreateClone();
			$newMe->Source($source);
			$x[] = &$newMe;
		}
		
		return new CManyTags($x);
	}
	
	function EachContent($many) {
		$x = array();
		foreach ($many as $source) {
			$newMe = &$this->CreateClone();
			$newMe->Content($source);
			$x[] = &$newMe;
		}
		
		return new CManyTags($x);
	}
}

class CManyTags extends CDynamic {
	var $Tags;
	function Init($tags) {
		$this->Tags = $tags;
	}
	
	function _CallMethod($name, $args, &$ret) {
		foreach ($this->Tags as $tag)
			call_user_func_array(array(&$tag, $name), $args);
			
		$ret = $this;
		return true;
	}
	
	function EachSource($many) {
		$l = sizeof($this->Tags) - 1;
		for ($i = 0; $i < sizeof($many); $i++) {
			if ($i > $l) return;
			$this->Tags[$i]->Source($many[$i]);
		}
		
		return $this;
	}

	function EachContent($many) {
		$l = sizeof($this->Tags) - 1;
		for ($i = 0; $i < sizeof($many); $i++) {
			if ($i > $l) return;
			$this->Tags[$i]->Content($many[$i]);
		}
		
		return $this;
	}
}

function CHEcho($x) {
	echo ($y = htmlspecialchars($x));
	return $y;
}

function CHEsc($x) {
	return htmlspecialchars($x);
}

function CShow(&$x) {
	if (is_object($x)) $x->Show();
	else CHEcho($x);
}

?>